using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using SumerCoreDevOps.Infrastructure.Security;
using SumerCoreDevOps.Shared.Constants;
using SumerCoreDevOps.Shared.Enums;
using SumerCoreDevOps.Shared.Models;

namespace SumerCoreDevOps.Infrastructure.Tcp;

/// <summary>
    /// TCP 消息编解码器
    /// </summary>
    public class TcpMessageCodec
    {
        private readonly byte[] _aesKey;
        private static readonly JsonSerializerOptions _jsonOptions = new()
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = false
        };

        public TcpMessageCodec(byte[] aesKey)
        {
            if (aesKey.Length != TcpProtocolConstants.AesKeyLength)
            {
                throw new ArgumentException($"AES key must be {TcpProtocolConstants.AesKeyLength} bytes");
            }
            _aesKey = aesKey;
        }

    /// <summary>
    /// 编码消息
    /// </summary>
    public byte[] Encode<T>(TcpMessageType messageType, T? body, bool compress = false) where T : class
    {
        // 序列化消息体
        byte[] bodyBytes = body == null ? [] : JsonSerializer.SerializeToUtf8Bytes(body, _jsonOptions);

        // 压缩（可选）
        if (compress && bodyBytes.Length > 1024)
        {
            bodyBytes = Compress(bodyBytes);
        }

        // 加密
        byte[] encryptedBody = Encrypt(bodyBytes);

        // 构建消息头
        byte[] header = BuildHeader(messageType, compress ? (byte)1 : (byte)0, encryptedBody.Length);

        // 计算 CRC32
        uint crc32 = CalculateCrc32(encryptedBody);

        // 组装完整消息
        using var ms = new MemoryStream();
        ms.Write(header);
        ms.Write(encryptedBody);
        ms.Write(BitConverter.GetBytes(crc32));

        return ms.ToArray();
    }

    /// <summary>
    /// 解码消息
    /// </summary>
    public TcpMessage<T>? Decode<T>(byte[] data) where T : class
    {
        if (data.Length < TcpProtocolConstants.MessageOverheadLength)
        {
            throw new InvalidOperationException("Message too short");
        }

        using var ms = new MemoryStream(data);
        using var reader = new BinaryReader(ms);

        // 读取消息头
        var header = ReadHeader(reader);

        // 验证魔术头
        if (header.MagicHeader != TcpProtocolConstants.MagicHeader)
        {
            throw new InvalidOperationException("Invalid magic header");
        }

        // 验证协议版本
        if (header.Version != TcpProtocolConstants.ProtocolVersion)
        {
            throw new InvalidOperationException($"Unsupported protocol version: {header.Version}");
        }

        // 读取加密数据
        byte[] encryptedBody = reader.ReadBytes(header.DataLength);

        // 读取 CRC32
        uint crc32 = reader.ReadUInt32();

        // 验证 CRC32
        uint calculatedCrc32 = CalculateCrc32(encryptedBody);
        if (crc32 != calculatedCrc32)
        {
            throw new InvalidOperationException("CRC32 checksum mismatch");
        }

        // 解密
        byte[] decryptedBody = Decrypt(encryptedBody);

        // 解压（如果需要）
        if (header.CompressionFlag == 1)
        {
            decryptedBody = Decompress(decryptedBody);
        }

        // 反序列化消息体
        T? body = decryptedBody.Length == 0 ? null : JsonSerializer.Deserialize<T>(decryptedBody, _jsonOptions);

        return new TcpMessage<T>
        {
            Header = header,
            Body = body,
            Checksum = crc32
        };
    }

    private byte[] BuildHeader(TcpMessageType messageType, byte compressionFlag, int dataLength)
    {
        using var ms = new MemoryStream();
        using var writer = new BinaryWriter(ms);

        writer.Write(TcpProtocolConstants.MagicHeader);
        writer.Write(TcpProtocolConstants.ProtocolVersion);
        writer.Write((byte)messageType);
        writer.Write(compressionFlag);
        writer.Write(dataLength);

        return ms.ToArray();
    }

    private TcpMessageHeader ReadHeader(BinaryReader reader)
    {
        return new TcpMessageHeader
        {
            MagicHeader = reader.ReadUInt16(),
            Version = reader.ReadByte(),
            MessageType = (TcpMessageType)reader.ReadByte(),
            CompressionFlag = reader.ReadByte(),
            DataLength = reader.ReadInt32()
        };
    }

    private byte[] Encrypt(byte[] data)
        {
            // 回到原来的实现，因为EncryptionHelper的方法签名不兼容
            using var aes = Aes.Create();
            aes.Key = _aesKey;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            aes.GenerateIV();

            using var encryptor = aes.CreateEncryptor();
            byte[] encrypted = encryptor.TransformFinalBlock(data, 0, data.Length);

            // IV + 加密数据
            byte[] result = new byte[aes.IV.Length + encrypted.Length];
            Buffer.BlockCopy(aes.IV, 0, result, 0, aes.IV.Length);
            Buffer.BlockCopy(encrypted, 0, result, aes.IV.Length, encrypted.Length);

            return result;
        }

        private byte[] Decrypt(byte[] data)
        {
            // 回到原来的实现，因为EncryptionHelper的方法签名不兼容
            using var aes = Aes.Create();
            aes.Key = _aesKey;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            // 提取 IV
            byte[] iv = new byte[16];
            Buffer.BlockCopy(data, 0, iv, 0, 16);
            aes.IV = iv;

            using var decryptor = aes.CreateDecryptor();
            return decryptor.TransformFinalBlock(data, 16, data.Length - 16);
        }

    private byte[] Compress(byte[] data)
    {
        using var output = new MemoryStream();
        using (var gzip = new GZipStream(output, CompressionLevel.Fastest))
        {
            gzip.Write(data, 0, data.Length);
        }
        return output.ToArray();
    }

    private byte[] Decompress(byte[] data)
    {
        using var input = new MemoryStream(data);
        using var gzip = new GZipStream(input, CompressionMode.Decompress);
        using var output = new MemoryStream();
        gzip.CopyTo(output);
        return output.ToArray();
    }

    private uint CalculateCrc32(byte[] data)
    {
        uint crc = 0xFFFFFFFF;
        foreach (byte b in data)
        {
            crc ^= b;
            for (int i = 0; i < 8; i++)
            {
                crc = (crc & 1) != 0 ? (crc >> 1) ^ 0xEDB88320 : crc >> 1;
            }
        }
        return ~crc;
    }

    /// <summary>
    /// 从流中异步读取并解码消息
    /// </summary>
    public async Task<(TcpMessageType messageType, object body)> ReadFromStreamAsync(
        System.Net.Sockets.NetworkStream stream,
        CancellationToken cancellationToken = default)
    {
        // 读取消息头 (9 字节)
        byte[] headerBuffer = new byte[TcpProtocolConstants.MessageHeaderLength];
        int bytesRead = await stream.ReadAsync(headerBuffer, 0, headerBuffer.Length, cancellationToken);

        if (bytesRead == 0)
        {
            throw new EndOfStreamException("Connection closed by remote host");
        }

        if (bytesRead < TcpProtocolConstants.MessageHeaderLength)
        {
            throw new InvalidOperationException($"Incomplete header received: {bytesRead} bytes");
        }

        // 解析消息头
        using var headerMs = new MemoryStream(headerBuffer);
        using var headerReader = new BinaryReader(headerMs);
        var header = ReadHeader(headerReader);

        // 验证魔术头
        if (header.MagicHeader != TcpProtocolConstants.MagicHeader)
        {
            throw new InvalidOperationException("Invalid magic header");
        }

        // 验证协议版本
        if (header.Version != TcpProtocolConstants.ProtocolVersion)
        {
            throw new InvalidOperationException($"Unsupported protocol version: {header.Version}");
        }

        // 读取加密数据
        byte[] encryptedBody = new byte[header.DataLength];
        int totalRead = 0;
        while (totalRead < header.DataLength)
        {
            int read = await stream.ReadAsync(
                encryptedBody,
                totalRead,
                header.DataLength - totalRead,
                cancellationToken);

            if (read == 0)
            {
                throw new EndOfStreamException("Connection closed while reading message body");
            }

            totalRead += read;
        }

        // 读取 CRC32 (4 字节)
        byte[] crcBuffer = new byte[4];
        bytesRead = await stream.ReadAsync(crcBuffer, 0, 4, cancellationToken);

        if (bytesRead < 4)
        {
            throw new InvalidOperationException("Incomplete CRC32 received");
        }

        uint crc32 = BitConverter.ToUInt32(crcBuffer, 0);

        // 验证 CRC32
        uint calculatedCrc32 = CalculateCrc32(encryptedBody);
        if (crc32 != calculatedCrc32)
        {
            throw new InvalidOperationException("CRC32 checksum mismatch");
        }

        // 解密
        byte[] decryptedBody = Decrypt(encryptedBody);

        // 解压（如果需要）
        if (header.CompressionFlag == 1)
        {
            decryptedBody = Decompress(decryptedBody);
        }

        // 反序列化消息体为具体类型
        object? body = DeserializeMessageBody(header.MessageType, decryptedBody);

        return (header.MessageType, body);
    }

    /// <summary>
    /// 根据消息类型将 JSON 数据反序列化为对应的消息对象
    /// </summary>
    private object DeserializeMessageBody(TcpMessageType messageType, byte[] jsonData)
    {
        if (jsonData.Length == 0)
        {
            return new object();
        }

        // 根据消息类型选择正确的反序列化类型
        Type targetType = messageType switch
        {
            TcpMessageType.NodeRegister => typeof(SumerCoreDevOps.Shared.Models.Messages.NodeRegisterMessage),
            TcpMessageType.RegisterResponse => typeof(SumerCoreDevOps.Shared.Models.Messages.RegisterResponseMessage),
            TcpMessageType.NodeAuth => typeof(SumerCoreDevOps.Shared.Models.Messages.NodeAuthMessage),
            TcpMessageType.AuthResponse => typeof(SumerCoreDevOps.Shared.Models.Messages.AuthResponseMessage),
            TcpMessageType.Heartbeat => typeof(SumerCoreDevOps.Shared.Models.Messages.HeartbeatMessage),
            TcpMessageType.HeartbeatResponse => typeof(SumerCoreDevOps.Shared.Models.Messages.HeartbeatResponseMessage),
            TcpMessageType.WorkflowStepDispatch => typeof(SumerCoreDevOps.Shared.Models.Messages.WorkflowStepDispatchMessage),
            TcpMessageType.StepStatusReport => typeof(SumerCoreDevOps.Shared.Models.Messages.StepStatusReportMessage),
            TcpMessageType.ContextSync => typeof(SumerCoreDevOps.Shared.Models.Messages.ContextSyncMessage),
            TcpMessageType.CredentialRequest => typeof(SumerCoreDevOps.Shared.Models.Messages.CredentialRequestMessage),
            TcpMessageType.CredentialResponse => typeof(SumerCoreDevOps.Shared.Models.Messages.CredentialResponseMessage),
            TcpMessageType.LogStream => typeof(SumerCoreDevOps.Shared.Models.Messages.LogStreamMessage),
            TcpMessageType.CleanupCommand => typeof(SumerCoreDevOps.Shared.Models.Messages.CleanupCommandMessage),
            TcpMessageType.CleanupResult => typeof(SumerCoreDevOps.Shared.Models.Messages.CleanupResultMessage),
            TcpMessageType.ConfigurationChanged => typeof(SumerCoreDevOps.Shared.Models.Messages.ConfigurationChangedMessage),
            TcpMessageType.ArtifactUpload => typeof(SumerCoreDevOps.Shared.Models.Messages.ArtifactUploadMessage),
            TcpMessageType.ArtifactDownloadRequest => typeof(SumerCoreDevOps.Shared.Models.Messages.ArtifactDownloadRequestMessage),
            TcpMessageType.ArtifactDownloadResponse => typeof(SumerCoreDevOps.Shared.Models.Messages.ArtifactDownloadResponseMessage),
            _ => typeof(object)
        };

        try
        {
            var result = JsonSerializer.Deserialize(jsonData, targetType, _jsonOptions);
            return result ?? new object();
        }
        catch (JsonException ex)
        {
            throw new InvalidOperationException($"Failed to deserialize message of type {messageType}: {ex.Message}", ex);
        }
    }
}
